<template>
  <div class="code-editor">
    <div class="code-editor-toolbar">
      语言
      <div class="select">
        <select v-model="defaultlang"  @change="selectLanguage">
          <option :value="item.value" v-for="item in langs">{{ item.label }}</option>
        </select>
      </div>
    </div>
    <textarea :ref="codeEditorid"></textarea>
  </div>
</template>

<script>
import CodeMirror from 'codemirror';
import '@/components/CodeEditor/setting.js';
//引入语言文件
//import 'codemirror/addon/mode/loadmode';
//import 'codemirror/mode/meta';
import 'codemirror/mode/xml/xml.js';
import 'codemirror/mode/css/css.js';
import 'codemirror/mode/javascript/javascript.js';
import 'codemirror/mode/htmlmixed/htmlmixed.js';
import 'codemirror/mode/clike/clike.js';
import 'codemirror/mode/python/python.js';
import 'codemirror/mode/htmlembedded/htmlembedded.js';
import 'codemirror/mode/sql/sql.js';
import 'codemirror/mode/go/go.js';
import 'codemirror/mode/vue/vue.js';
import 'codemirror/mode/php/php.js';

const tips = '//按Ctrl键进行代码提示,双击清空';

export default {
  name: 'codeEditor',
  /* eslint-disable vue/require-prop-types */
  props: {
    id: {
      type: String,
      default: function() {
        return 'codeEditorTextarea-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
      }
    },
    value: {
      type: String,
      default: tips
    }
  },
  data() {
    return {
      codeEditor: false,
      codeEditorid: this.id,
      langs: [
        {
          value: 'text/html',
          label: 'HTML',
          prism:'markup'   //prism高亮
        },
        {
          value: 'text/javascript',
          label: 'JavaScript',
          prism:'javascript'
        },
        {
          value: 'text/css',
          label: 'CSS',
          prism:'css'
        },
        {
          value: 'application/xml',
          label: 'XML',
          prism:'xml'
        },
        {
          value: 'text/x-java',
          label: 'JAVA',
          prism:'java'
        },
        {
          value: 'text/x-csharp',
          label: 'C#',
          prism:'csharp'
        },

        {
          value: 'application/x-aspx',
          label: 'ASP.NET',
          prism:'aspnet'
        },
        {
          value: 'text/x-c++src',
          label: 'C++',
          prism:'cpp'
        },
        {
          value: 'text/x-csrc',
          label: 'C',
          prism:'c'
        },
        {
          value: 'text/x-python',
          label: 'Python',
          prism:'python'
        },
        {
          value: 'text/x-sql',
          label: 'sql',
          prism:'sql'
        },
        {
          value: 'text/x-go',
          label: 'go',
          prism:'go'
        },
        {
          value: 'application/json',
          label: 'JSON',
          prism:'json'
        },
        {
          value: 'script/x-vue',
          label: 'Vue.js',
          prism:'js'
        },
        {
          value: 'text/x-php',
          label: 'PHP',
          prism:'php'
        }
      ],
      defaultlang: 'text/html'
    };
  },
  watch: {
    value(value) {
      const editorValue = this.codeEditor.getValue();
      if (value !== editorValue) {
        this.codeEditor.setValue(this.value);
      }
    }
  },
  mounted() {
    var that = this;
    //let mime = 'text/x-mariadb'
    let theme = 'rubyblue'; //设置主题，不设置的会使用默认主题
    that.codeEditor = CodeMirror.fromTextArea(this.$refs[this.codeEditorid], {
      indentWithTabs: true,
      smartIndent: true, //自动缩进是否开启
      indentUnit: 4, //缩进单位
      styleActiveLine: true, // 高亮选中行
      lineNumbers: true,
      matchBrackets: true,
      lint: true,
      line: true,
      foldGutter: true, // 块槽
      gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'CodeMirror-lint-markers'],
      theme: theme,
      //autofocus: true,
      mode: this.defaultlang, //选择对应代码编辑器的语言 // 模式, 可查看 codemirror/mode 中的所有模式
      // hint.js options
      hintOptions: {
        // 当匹配只有一项的时候是否自动补全
        completeSingle: false
      },
      // 快捷键 可提供三种模式 sublime、emacs、vim
      keyMap: 'sublime',
      showCursorWhenSelecting: true,
      extraKeys: { Ctrl: 'autocomplete', Backspace: 'delCharBefore', Delete: 'delCharAfter' }, //extraKeys 快捷键,例如 {“Ctrl-Q”: “autocomplete”}：自动补全使用需要引入工具。自定义快捷键,可以用于为编辑器指定额外的键绑定，以及keyMap定义的键绑定
      hintOptions: {
        //自定义提示选项
        tables: {
          users: ['name', 'score', 'birthDate'],
          countries: ['name', 'population', 'size']
        }
      }
    });
    this.codeEditor.setValue(this.value);
    //代码自动提示功能，记住使用cursorActivity事件不要使用change事件，这是一个坑，那样页面直接会卡死
    that.codeEditor.on('keypress', cm => {
      that.codeEditor.showHint();
      that.$emit('changed', cm.getValue());
      that.$emit('input', cm.getValue());
    });
    that.codeEditor.on('dblclick', cm => {
      if (cm.getValue() == tips) {
        cm.setValue('');
      }
    });
    /* that.jsonEditor.on('change', cm => {
      that.$emit('changed', cm.getValue())
      that.$emit('input', cm.getValue())
    }) */
    //动态设置CodeMirror属性：(以设置支持语言mode为例)
    //this.CodeMirrorEditor.setOption("mode",this.something)
  },
  methods: {
    selectLanguage(e) {
     if(!this.codeEditor)return;
     var mode=this.defaultlang
     if (mode) {
        //CodeMirror.autoLoadMode(this.codeEditor, mode);alert(CodeMirror.modeURL)
        this.codeEditor.setOption("mode", mode);
     }
    },
    init(data) {
       if(data &&data.code){
         for(var idx in this.langs){
            var item=this.langs[idx]
            if(item.prism==data.language) {
              this.defaultlang=item.value
              this.selectLanguage()
            }
         }
         this.codeEditor.setValue(data.code);
         //解决codeMirror使用setValue更新数据之后需要获取到焦点才会在展示上更新
         setTimeout(() => {
             this.codeEditor.refresh()
         }, 1)
       }else{
         this.codeEditor.setValue(tips);      
       }
    },
    getPrism() {
      for(var idx in this.langs){
         var item=this.langs[idx]
         if(item.value==this.defaultlang) return item.prism;
      }
    },
    getValue() {
      return this.codeEditor.getValue();
    }
  }
};
</script>

<style scoped>
.code-editor {
  height: 100%;
  position: relative;
  font-size: 16px;
  line-height: 150%;
}
.code-editor >>> .CodeMirror {
  height: auto;
  height: 400px;
}
.code-editor >>> .CodeMirror-scroll {
  height: 400px;
}
.code-editor >>> .cm-s-rubyblue span.cm-string {
  color: #f08047;
}
.code-editor-toolbar{
  margin-bottom: 2px;;
  }
.select {
  display: inline-block;
  width: 120px;
  position: relative;
  vertical-align: middle;
  padding: 0;
  overflow: hidden;
  background-color: #fff;
  color: #555;
  border: 1px solid #aaa;
  text-shadow: none;
  border-radius: 4px;
  transition: box-shadow 0.25s ease;
  z-index: 2;
}

.select:hover {
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
}

.select:before {
  content: '';
  position: absolute;
  width: 0;
  height: 0;
  border: 10px solid transparent;
  border-top-color: #ccc;
  top: 14px;
  right: 10px;
  cursor: pointer;
  z-index: -2;
}
.select select {
  cursor: pointer;
  padding: 6px;
  width: 100%;
  border: none;
  background: transparent;
  background-image: none;
  -webkit-appearance: none;
  -moz-appearance: none;
}

.select select:focus {
  outline: none;
}
</style>
